/**
 * wht-request 请求插件
 * @description 一个支持多端的请求插件，支持请求拦截、响应拦截、全局配置等功能
 * @version 1.0.0
 */

class WhtRequest {
    constructor(options = {}) {
        // 默认配置
        this.config = {
            baseURL: '',
            header: {},
            timeout: 60000,
            validateStatus: (status) => status >= 200 && status < 300,
            ...options
        }
        
        // 拦截器
        this.interceptors = {
            request: [],
            response: []
        }

        // 任务管理
        this.tasks = new Map()
    }

    /**
     * 创建新的请求实例
     * @param {Object} options - 配置项
     * @returns {WhtRequest} - 新的请求实例
     */
    static create(options) {
        return new WhtRequest(options)
    }

    /**
     * 添加请求拦截器
     * @param {Function} onFulfilled - 成功回调
     * @param {Function} onRejected - 失败回调
     * @returns {Function} - 移除拦截器的函数
     */
    addRequestInterceptor(onFulfilled, onRejected) {
        const interceptor = {
            onFulfilled,
            onRejected
        }
        this.interceptors.request.push(interceptor)
        
        // 返回移除拦截器的函数
        return () => {
            const index = this.interceptors.request.indexOf(interceptor)
            if (index !== -1) {
                this.interceptors.request.splice(index, 1)
            }
        }
    }

    /**
     * 添加响应拦截器
     * @param {Function} onFulfilled - 成功回调
     * @param {Function} onRejected - 失败回调
     * @returns {Function} - 移除拦截器的函数
     */
    addResponseInterceptor(onFulfilled, onRejected) {
        const interceptor = {
            onFulfilled,
            onRejected
        }
        this.interceptors.response.push(interceptor)
        
        // 返回移除拦截器的函数
        return () => {
            const index = this.interceptors.response.indexOf(interceptor)
            if (index !== -1) {
                this.interceptors.response.splice(index, 1)
            }
        }
    }

    /**
     * 执行请求拦截器
     * @param {Object} config - 请求配置
     * @returns {Promise} - 处理后的配置
     */
    async _runRequestInterceptors(config) {
        let currentConfig = { ...config }
        for (let interceptor of this.interceptors.request) {
            try {
                currentConfig = await interceptor.onFulfilled(currentConfig)
            } catch (error) {
                if (interceptor.onRejected) {
                    currentConfig = await interceptor.onRejected(error)
                }
                throw error
            }
        }
        return currentConfig
    }

    /**
     * 执行响应拦截器
     * @param {Object} response - 响应数据
     * @returns {Promise} - 处理后的响应
     */
    async _runResponseInterceptors(response) {
        let currentResponse = { ...response }
        for (let interceptor of this.interceptors.response) {
            try {
                currentResponse = await interceptor.onFulfilled(currentResponse)
            } catch (error) {
                if (interceptor.onRejected) {
                    currentResponse = await interceptor.onRejected(error)
                }
                throw error
            }
        }
        return currentResponse
    }

    /**
     * 处理请求参数
     * @param {Object} options - 请求配置
     * @returns {Object} - 处理后的配置
     */
    _processConfig(options) {
        const config = {
            ...this.config,
            ...options,
            header: { ...this.config.header, ...options.header }
        }

        // 处理 URL
        if (config.baseURL && !options.url.startsWith('http')) {
            config.url = config.baseURL + options.url
        }

        // 处理请求参数
        if (config.params) {
            const queryString = Object.entries(config.params)
                .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
                .join('&')
            config.url += (config.url.includes('?') ? '&' : '?') + queryString
        }

        return config
    }

    /**
     * 发起请求
     * @param {Object} options - 请求配置
     * @returns {Promise} - 请求Promise
     */
    async request(options) {
        // 处理配置
        const config = this._processConfig(options)

        // 执行请求拦截器
        try {
            await this._runRequestInterceptors(config)
        } catch (error) {
            return Promise.reject(error)
        }

        // 发起请求
        return new Promise((resolve, reject) => {
            const task = uni.request({
                ...config,
                success: async (res) => {
                    // 验证状态码
                    if (!this.config.validateStatus(res.statusCode)) {
                        reject({
                            statusCode: res.statusCode,
                            errMsg: `Request failed with status code ${res.statusCode}`,
                            data: res.data
                        })
                        return
                    }

                    try {
                        const response = await this._runResponseInterceptors(res)
                        resolve(response)
                    } catch (error) {
                        reject(error)
                    }
                },
                fail: (err) => {
                    reject(err)
                },
                complete: () => {
                    this.tasks.delete(config.url)
                }
            })

            // 保存任务实例
            if (task) {
                this.tasks.set(config.url, task)
                
                // 如果配置了 onUploadProgress 或 onDownloadProgress
                if (config.onUploadProgress && task.onProgressUpdate) {
                    task.onProgressUpdate((res) => {
                        config.onUploadProgress(res)
                    })
                }
            }
        })
    }

    /**
     * 上传文件
     * @param {Object} options - 上传配置
     * @returns {Promise} - 上传Promise
     */
    upload(options) {
        const config = this._processConfig(options)
        
        return new Promise((resolve, reject) => {
            const task = uni.uploadFile({
                ...config,
                
                success: async (res) => {
                    try {
                        // 尝试解析返回的数据为 JSON
                        if (typeof res.data === 'string') {
                            try {
                                res.data = JSON.parse(res.data)
                            } catch (e) {
                                // 如果解析失败，保持原样
                            }
                        }
                        
                        const response = await this._runResponseInterceptors(res)
                        resolve(response)
                    } catch (error) {
                        reject(error)
                    }
                },
                fail: reject,
                complete: () => {
                    this.tasks.delete(config.url)
                }
            })

            if (task) {
                this.tasks.set(config.url, task)
                if (config.onUploadProgress && task.onProgressUpdate) {
                    task.onProgressUpdate((res) => {
                        config.onUploadProgress(res)
                    })
                }
            }
        })
    }

    /**
     * 下载文件
     * @param {Object} options - 下载配置
     * @returns {Promise} - 下载Promise
     */
    download(options) {
        const config = this._processConfig(options)
        
        return new Promise((resolve, reject) => {
            const task = uni.downloadFile({
                ...config,
                success: async (res) => {
                    try {
                        const response = await this._runResponseInterceptors(res)
                        resolve(response)
                    } catch (error) {
                        reject(error)
                    }
                },
                fail: reject,
                complete: () => {
                    this.tasks.delete(config.url)
                }
            })

            if (task) {
                this.tasks.set(config.url, task)
                if (config.onDownloadProgress && task.onProgressUpdate) {
                    task.onProgressUpdate((res) => {
                        config.onDownloadProgress(res)
                    })
                }
            }
        })
    }

    /**
     * 取消请求
     * @param {String} url - 请求URL
     */
    abort(url) {
        const task = this.tasks.get(url)
        if (task && task.abort) {
            task.abort()
            this.tasks.delete(url)
        }
    }

    /**
     * 取消所有请求
     */
    abortAll() {
        for (const [url, task] of this.tasks) {
            if (task && task.abort) {
                task.abort()
            }
        }
        this.tasks.clear()
    }

    // GET请求
    get(url, data = {}, options = {}) {
        return this.request({
            url,
            data,
            method: 'GET',
            ...options
        })
    }

    // POST请求
    post(url, data = {}, options = {}) {
        return this.request({
            url,
            data,
            method: 'POST',
            ...options
        })
    }

    // PUT请求
    put(url, data = {}, options = {}) {
        return this.request({
            url,
            data,
            method: 'PUT',
            ...options
        })
    }

    // DELETE请求
    delete(url, data = {}, options = {}) {
        return this.request({
            url,
            data,
            method: 'DELETE',
            ...options
        })
    }
}

export default WhtRequest;
